package ClassicalCryptography;

import NumTheory.NumTheory;

import java.math.BigInteger;

public class AffineCipher {
    public String encrypt(String plaintext, int a, int b) throws Exception {
        // 如果a和26的公约数不为1，则报错
        NumTheory numTheory = new NumTheory();
        if (numTheory.euclid(BigInteger.valueOf(a), BigInteger.valueOf(26)).compareTo(BigInteger.ONE) != 0) {
            throw new Exception("参数a需要与26互素！");
        }

        StringBuilder res = new StringBuilder(plaintext.length());
        int temp = -1;
        for (int i = 0; i < plaintext.length(); i++) {
            temp = plaintext.charAt(i) - 'a';
            res.append((char) ((temp * a + b) % 26 + 'a'));
        }
        return res.substring(0);
    }

    public String decrypt(String ciphertext, int a, int b) throws Exception {

        // 如果a和26的公约数不为1，则报错
        NumTheory numTheory = new NumTheory();
        if (numTheory.euclid(BigInteger.valueOf(a), BigInteger.valueOf(26)).compareTo(BigInteger.ONE) != 0) {
            throw new Exception("参数a需要与26互素！");
        }

        int aInv = BigInteger.valueOf(a).modInverse(BigInteger.valueOf(26)).intValue();

        StringBuilder res = new StringBuilder(ciphertext.length());
        int temp = -1;
        for (int i = 0; i < ciphertext.length(); i++) {
            temp = ciphertext.charAt(i) - 'a';
            int x = (aInv * (temp - b)) % 26;
            while (x < 0) {
                x += 26;
            }
            res.append((char) (x + 'a'));
        }
        return res.substring(0);
    }
}
